package com.hyt.it.ogt.kq.service.bm.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hyt.common.apiInfor.ApiResponse;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.enums.DelFlagEnum;
import com.hyt.core.util.UUIDUtils;
import com.hyt.exception.exception.BusinessLogicException;
import com.hyt.it.ogt.cj.service.IProjectCollectInfoOptionService;
import com.hyt.it.ogt.cj.service.IProjectCollectInfoService;
import com.hyt.it.ogt.kq.common.bm.enums.BmAuditInfoSubmitAgainStatus;
import com.hyt.it.ogt.kq.common.bm.enums.BmAuditStatusEnum;
import com.hyt.it.ogt.kq.common.bm.enums.BmPayStatusEnum;
import com.hyt.it.ogt.kq.common.bm.enums.BmProjectNeedAuditEnum;
import com.hyt.it.ogt.kq.common.bm.utils.Constant;
import com.hyt.it.ogt.kq.common.config.ConfigManager;
import com.hyt.it.ogt.kq.common.gov.constant.ResponseCode;
import com.hyt.it.ogt.kq.common.gov.utils.Constants;
import com.hyt.it.ogt.kq.common.utils.KqStringUtils;
import com.hyt.it.ogt.kq.service.bm.den.ShortMessage;
import com.hyt.it.ogt.kq.service.bm.mapper.ProjectMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.StudentInfoMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.StudentProjectMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.StudentSubjectMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.StudentVerifyMapper;
import com.hyt.it.ogt.kq.service.bm.model.entity.Dict;
import com.hyt.it.ogt.kq.service.bm.model.entity.NonOpenInfo;
import com.hyt.it.ogt.kq.service.bm.model.entity.Project;
import com.hyt.it.ogt.kq.service.bm.model.entity.ProjectExam;
import com.hyt.it.ogt.kq.service.bm.model.entity.ProjectSubject;
import com.hyt.it.ogt.kq.service.bm.model.entity.ProjectSubjectAreaLimit;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentInfo;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentProject;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentSubject;
import com.hyt.it.ogt.kq.service.bm.model.entity.StudentVerify;
import com.hyt.it.ogt.kq.service.bm.model.vo.StuSubjectVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.StudentVerifyVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.StudentVo;
import com.hyt.it.ogt.kq.service.bm.service.IDictService;
import com.hyt.it.ogt.kq.service.bm.service.INonOpenService;
import com.hyt.it.ogt.kq.service.bm.service.IProjectExamService;
import com.hyt.it.ogt.kq.service.bm.service.IProjectService;
import com.hyt.it.ogt.kq.service.bm.service.IProjectSubjectAreaLimitService;
import com.hyt.it.ogt.kq.service.bm.service.IProjectSubjectService;
import com.hyt.it.ogt.kq.service.bm.service.IStudentInfoService;
import com.hyt.it.ogt.kq.service.bm.service.IStudentProjectService;
import com.hyt.it.ogt.kq.service.bm.service.IStudentSubjectService;
import com.hyt.it.ogt.kq.service.bm.service.IStudentVerifyService;
import com.hyt.it.ogt.kq.service.bm.service.stcenter.IStcenterStudentPayService;
import com.hyt.it.ogt.kq.service.gov.api.bm.BmApi;
import com.hyt.it.ogt.kq.service.gov.service.ITaskOverviewService;
import com.hyt.it.ogt.kq.service.model.param.PushCandidateSubjectParam;
import com.hyt.loginfo.util.UserIdToNameUtil;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 考生审核表 服务实现类
 * </p>
 *
 * @author wangt
 * @since 2020-05-15
 */
@Slf4j
@Service
public class StudentVerifyServiceImpl extends BaseServiceImpl<StudentVerifyMapper, StudentVerify> implements IStudentVerifyService {

    private final Logger logger = LoggerFactory.getLogger(StudentVerifyServiceImpl.class);

    @Resource
    private StudentVerifyMapper studentVerifyMapper;
    @Resource
    private IProjectService iProjectService;
    @Resource
    private StudentSubjectMapper studentSubjectMapper;
    @Resource
    private ConfigManager configManager;
    @Resource
    private StudentInfoMapper studentInfoMapper;
    @Resource
    private ShortMessage shortMessage;
    @Resource
    private IDictService dictService;
    @Resource
    protected UserIdToNameUtil<StudentVerify> userIdToNameUtil;
    @Resource
    ITaskOverviewService iTaskOverviewService;
    @Resource
    IStudentSubjectService iStudentSubjectService;
    @Resource
    IStudentProjectService iStudentProjectService;
    @Resource
    private IStcenterStudentPayService iStcenterStudentPayService;
    @Resource
    IProjectExamService iProjectExamService;
    @Resource
    IProjectSubjectService iProjectSubjectService;
    @Resource
    private IProjectCollectInfoService iProjectCollectInfoService;
    @Resource
    private IProjectCollectInfoOptionService iProjectCollectInfoOptionService;
    @Resource
    private BmApi kwGovClient;
    @Resource
    private IStudentInfoService iStudentInfoService;
    @Resource
    StudentProjectMapper studentProjectMapper;
    @Resource
    ProjectMapper projectMapper;
    @Resource
    INonOpenService iNonOpenService;
    @Resource
    private IProjectSubjectAreaLimitService iProjectSubjectAreaLimitService;

    @Override
    public void updateAudit(StudentVerify sVerify) {
        String bmInformationSubmitAgain = BmAuditInfoSubmitAgainStatus.INIT.getStatus();
        // 修改项目考生的审核状态
        if (BmAuditStatusEnum.UNAPPROVED.getAuditStatus().equals(sVerify.getVerifyStatus())) {
            bmInformationSubmitAgain = BmAuditInfoSubmitAgainStatus.UNSUPPLEMENTARY.getStatus();
        }
        sVerify.setBmInformationSubmitAgain(bmInformationSubmitAgain);
        studentVerifyMapper.updateAudit(sVerify);
        // 修改科目的审核状态
        studentSubjectMapper.updateStudentSubjectAudit(sVerify.getProjectId(), sVerify.getStudentId(), sVerify.getVerifyStatus());
    }

    @Override
    public List<StudentVerify> getStuByAuditStatus(List<String> stuIds) {
        return studentVerifyMapper.getStuByAuditStatus(stuIds);
    }

    @Override
    public String getSubjectName(String subjectId, String projectId) {
        return studentVerifyMapper.getSubjectName(subjectId, projectId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResponse<Object> auditStudentSubject(StudentVerify sVerify) {
        // 审核的考生id
        List<String> stuIds = Arrays.asList(sVerify.getStudentId().split(","));
        if (CollUtil.isEmpty(stuIds)) {
            return ApiResponse.builder().code(31111304).data("审核考生失败！考生列表不能为空").build();
        }

        // 考生已经导入到考务，不可以再次审核
        List<StudentVerify> studentVerifys = getStuByAuditStatus(stuIds);
        if (CollectionUtils.isNotEmpty(studentVerifys)) {
            return ApiResponse.builder().code(31111305).data("审核考生失败！考生已经导入到考务，不可以再次审核").build();
        }
        // 判断是否已经过了审核时间
        String projectId = sVerify.getProjectId();
        if (StrUtil.isEmptyIfStr(projectId)) {
            return ApiResponse.builder().code(31111306).data("报名项目不存在").build();
        }
        // 查询项目信息
        Project project = iProjectService.getById(sVerify.getProjectId());
        if (null == project) {
            return ApiResponse.builder().code(31111306).data("报名项目不存在").build();
        }
        // 如果项目需要审核
        if (BmProjectNeedAuditEnum.NEEDAUDIT.getAuditStatus().equals(project.getIsVerify()) && null != project.getAuditEndTime() && LocalDateTime.now().isAfter(project.getAuditEndTime())) {
            return ApiResponse.builder().code(31111303).data("报名项目已经超过审核时间！").build();
        }
        for (String stuId : stuIds) {
//            // 如果科目的状态是已缴费则不需要二次审核
//            QueryWrapper<StudentSubject> queryWrapper = new QueryWrapper<>();
//            queryWrapper.lambda().eq(StudentSubject::getProjectId, project.getId()).eq(StudentSubject::getStudentId, stuId).notIn(StudentSubject::getPay, BmPayStatusEnum.PAY.getPayStatus());
//            List<StudentSubject> studentSubjectList = studentSubjectMapper.selectList(queryWrapper);
//            if (CollUtil.isEmpty(studentSubjectList)) {
//                continue;
//            }
            sVerify.setId(UUIDUtils.newSortUUID());
            sVerify.setStudentId(stuId);
            // 保存审核记录log
            save(sVerify);
            // 修改科目的审核状态
            updateAudit(sVerify);
        }

        for (String stuId : stuIds) {
            try {
                // 审核不通过
                if (BmAuditStatusEnum.UNAPPROVED.getAuditStatus().equals(sVerify.getVerifyStatus())) {
                    String sendauditcase = configManager.getSendauditcase();
                    if (StrUtil.isNotBlank(sendauditcase) && Boolean.valueOf(sendauditcase)) {
                        StudentVo studentVo = studentInfoMapper.getStuInfoByStudentId(sVerify.getProjectId(), stuId);
                        String phone = studentVo.getPhone();
                        if (StringUtils.isNoneEmpty(phone)) {
                            String template = configManager.getAuditnopasstemplete();
                            String content = String.format(template, project.getProjectName());
                            shortMessage.setMessage(phone.split(","), content);
                            shortMessage.sendMessage("bmauditnopass");
                        }
                    }
                }
            } catch (Exception e) {
                logger.error("[报名管理端][审核考生] audit sendMessage error", e);
            }
        }

        // 获取还未审核的考生ID
        String nextToBeAuditStudent = studentProjectMapper.getNextToBeAuditStudent(projectId);
        return ApiResponse.builder()
                .code(Constant.RESPONSE_CODE_SUCCESS)
                .data(nextToBeAuditStudent)
                .build();
    }

    @Override
    public void deleteStudentSubject(StudentSubject studentSubject) {
        String studentId = studentSubject.getStudentId();
        String subjectId = studentSubject.getSubjectId();
        if (KqStringUtils.isBlank(studentId)) {
            BusinessLogicException.throwException(Constant.RESPONSE_CODE_31010180, "未选择考生！");
        }
        if (KqStringUtils.isBlank(subjectId)) {
            BusinessLogicException.throwException(31010196, "未选择科目！");
        }
        StudentProject studentProject = iStudentProjectService.getById(studentId);
        boolean hasPay = iStcenterStudentPayService.querystudentSubjectPayRecord(studentId, subjectId, studentProject.getProjectId());
        if (hasPay) {
            BusinessLogicException.throwException(Constant.RESPONSE_CODE_31111501, "考生已缴费，不能删除", studentProject);
        }
        iStudentSubjectService.deleteStudentSubject(studentId, subjectId);
        // 查询数据库数据存在科目
        QueryWrapper<StudentSubject> studentSubjectQueryWrapper = new QueryWrapper<>();
        studentSubjectQueryWrapper.lambda()
                .eq(StudentSubject::getStudentId, studentId)
                .eq(StudentSubject::getDelFlag, Boolean.FALSE);
        int dbStudentSubjectCount =  iStudentSubjectService.count(studentSubjectQueryWrapper);
        if(dbStudentSubjectCount == 0) {
            QueryWrapper<StudentInfo> studentQueryWrapper = new QueryWrapper<>();
            studentQueryWrapper.lambda()
                .eq(StudentInfo::getProjectId, studentProject.getProjectId())
                .eq(StudentInfo::getStudentId, studentId)
                .eq(StudentInfo::getDelFlag, Boolean.FALSE);
            List<StudentInfo> studentInfos =  iStudentInfoService.list(studentQueryWrapper);
            // 修改报名资格为已报考
            List<NonOpenInfo> nonOpenInfos = iNonOpenService.getStudentQualificationByIdcard(studentProject.getProjectId(), studentInfos);
            if(CollUtil.isNotEmpty(nonOpenInfos)) {
                for (NonOpenInfo nonOpenInfo : nonOpenInfos) {
                    nonOpenInfo.setIsBm(Boolean.FALSE);
                }
                iNonOpenService.saveOrUpdateBatch(nonOpenInfos);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addSubject(StuSubjectVo stuSubjectVo) {
        String studentId = stuSubjectVo.getStudentId();
        String projectId = stuSubjectVo.getProjectId();
        String subjectIdList = stuSubjectVo.getSubjectIdList();
        List<String> subjectIds = StrUtil.splitTrim(subjectIdList, StrPool.COMMA);
        subjectIds = CollUtil.distinct(subjectIds);

        Project project = iProjectService.getById(stuSubjectVo.getProjectId());
        if (CollUtil.size(subjectIds) > project.getMaxSubject()) {
            BusinessLogicException.throwException(31111602, "报名科目失败，实际报名科目数大于最多报名科目数！", project);
        }

        // 获取考生的采集信息
        List<StudentInfo> studentInfos = iStudentInfoService.listByStudentId(projectId, studentId);
        if (CollUtil.isEmpty(studentInfos)) {
            BusinessLogicException.throwException(31111603, "未查询到考生的采集信息", studentId);
        }
        // 校验报名考生是否有资格
        iNonOpenService.checkStudentHasQualifications(projectId, studentInfos, subjectIds);

        for (String subjectId : subjectIds) {
            StudentSubject objSubject = iStudentSubjectService.getStudentSbject(subjectId, studentId, projectId);
            if (objSubject != null) {
                continue;
            }
            // 获取当前科目
            StudentSubject obj = new StudentSubject();
            ProjectSubject projectSubject = iProjectSubjectService.queryBySubjectId(projectId, subjectId);
            if (projectSubject == null) {
                BusinessLogicException.throwException(31111607, "当前操作的科目未在报名项目中检索到", subjectId);
            } else {
                obj.setId(UUIDUtils.newSortUUID())
                        .setCreateBy(stuSubjectVo.getCurrentLoginUserId())
                        .setUpdateBy(stuSubjectVo.getCurrentLoginUserId())
                        .setCreateDate(LocalDateTime.now())
                        .setUpdateDate(LocalDateTime.now());
                obj.setSubjectId(subjectId);
                obj.setProjectId(projectId);
                obj.setStudentId(studentId);
                obj.setSubjectName(projectSubject.getSubjectName());
                obj.setIsPay(projectSubject.getIsPay());
                obj.setIsAudit(BmAuditStatusEnum.PENDINGAPPROVAL.getAuditStatus());
            }
            



            // 集体报名默认报考所有科目，这个时候需要将报考的科目和配置的最大报考名额做校验
            Boolean validateStudentSubjectRegistNum = iStudentSubjectService.validateStudentSubjectRegistNum(projectId, subjectId);
            if (!validateStudentSubjectRegistNum) {
                BusinessLogicException.throwException(31081205, "科目配置的报名名额不足，请选择其他科目进行报考！");
            }
            // 获取报名区域 studentId
            String bmAreaCollId = projectMapper.getCollectIdByProject(ProjectSubjectAreaLimit.getBmAreaCollKey(), projectId, DelFlagEnum.NORMAL.getCode());
            // 获取报名考生数据
            if (CharSequenceUtil.isNotEmpty(bmAreaCollId)) {
                String bmArea = iStudentInfoService.getValueByStudentIdAndCollectInfoId(projectId, studentId, bmAreaCollId);
                // 如果考生选择了报考区域
                if(StrUtil.isNotEmpty(bmArea)) {
                    Boolean checkExcess = iProjectSubjectAreaLimitService.checkExcessBySubjectIdAndArea(projectId, studentId, subjectId, bmAreaCollId,  bmArea);
                    if (checkExcess) {
                        BusinessLogicException.throwException(31101203,"您选择的时间段内此科目已报满，请选择其他时间段或科目。");
                    }
                } else { // 如果考生没有选择报考区域
                    Boolean checkSubjectConfigLimit = iProjectSubjectAreaLimitService.checkSubjectConfigLimit(projectId, subjectId);
                    if (checkSubjectConfigLimit) {
                        BusinessLogicException.throwException(31101204, "预约科目配置了区域限额，请先填写基本信息选择报考区域");
                    }
                }
            }
            iStudentSubjectService.save(obj);
        }
        
        // 修改报名资格为已报考
        List<NonOpenInfo> nonOpenInfos = iNonOpenService.getStudentQualificationByIdcard(projectId, studentInfos);
        if(CollUtil.isNotEmpty(nonOpenInfos)) {
            for (NonOpenInfo nonOpenInfo : nonOpenInfos) {
                nonOpenInfo.setIsBm(Boolean.TRUE);
            }
            iNonOpenService.saveOrUpdateBatch(nonOpenInfos);
        }
        
        iStudentSubjectService.updateStudentAudit(studentId, projectId);
    }


    @Override
    public List<StudentVerifyVo> queryAuditStudentCauseList(String projectId, String studentId) {
        if (StrUtil.isEmptyIfStr(projectId) || StrUtil.isEmptyIfStr(studentId)) {
            return Collections.emptyList();
        }
        Map<String, String> typevalueMap = new HashMap<>();
        List<Dict> dictList = dictService.getByType("audit_reject_reason_type");
        if (CollUtil.isNotEmpty(dictList)) {
            for (Dict dict : dictList) {
                typevalueMap.put(dict.getValue(), dict.getLabel());
            }
        }
        List<StudentVerifyVo> studentVerifyVos = new ArrayList<>();
        List<StudentVerify> studentVerifies = studentVerifyMapper.queryAuditStudentCauseList(projectId, studentId, BmAuditStatusEnum.UNAPPROVED.getAuditStatus());
        if (CollUtil.isNotEmpty(studentVerifies)) {
            for (StudentVerify studentVerify : studentVerifies) {
                StudentVerifyVo studentVerifyVo = new StudentVerifyVo();
                BeanUtil.copyProperties(studentVerify, studentVerifyVo);
                studentVerifyVo.setAuditRejectReasonTypeDesc(typevalueMap.get(studentVerify.getAuditRejectReasonType()));
                studentVerifyVo.setVerifyStatusDesc(BmAuditStatusEnum.getAuditStatusDesc(studentVerify.getVerifyStatus()));
                String verifyByName = userIdToNameUtil.getName(studentVerify.getVerifyBy());
                studentVerifyVo.setVerifyByName(verifyByName);
                studentVerifyVos.add(studentVerifyVo);
            }
        }
        return studentVerifyVos;
    }
}
